package me.zhengjie.modules.system.service.impl

import cn.hutool.core.collection.CollectionUtil
import me.zhengjie.common.utils.*
import me.zhengjie.common.utils.FileUtil.downloadExcel
import me.zhengjie.modules.system.domain.*
import me.zhengjie.modules.system.repository.DictRepository
import me.zhengjie.modules.system.service.DictService
import me.zhengjie.modules.system.service.dto.DictDTO
import me.zhengjie.modules.system.service.dto.DictQueryCriteria
import me.zhengjie.modules.system.service.mapper.DictMapper
import jakarta.persistence.criteria.CriteriaBuilder
import jakarta.persistence.criteria.CriteriaQuery
import jakarta.persistence.criteria.Root
import jakarta.servlet.http.HttpServletResponse
import org.springframework.cache.annotation.CacheConfig
import org.springframework.cache.annotation.CacheEvict
import org.springframework.cache.annotation.Cacheable
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Propagation
import org.springframework.transaction.annotation.Transactional
import java.io.IOException

/**
 * @author Kuki Wu
 * @date 2019-04-10
 */
@Service
@CacheConfig(cacheNames = ["dict"])
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = [Exception::class])
class DictServiceImpl(private val dictRepository: DictRepository, private val dictMapper: DictMapper) : DictService {
    @Cacheable(key = "'queryall_cp:'")
    override fun queryAll(dict: DictQueryCriteria, pageable: Pageable?): Any? {
        val page = dictRepository.findAll(
            { root: Root<Dict?>, query: CriteriaQuery<*>?, cb: CriteriaBuilder ->
                QueryHelp.getPredicate(
                    root,
                    dict,
                    cb
                )
            }, pageable!!
        )
        return PageUtil.toPage(page.map { entity: Dict? -> dictMapper.toDto(entity) })
    }

    @Cacheable(key = "'queryall_c'")
    override fun queryAll(dict: DictQueryCriteria): List<DictDTO> {
        val list = dictRepository.findAll { root: Root<Dict?>, query: CriteriaQuery<*>?, cb: CriteriaBuilder ->
            QueryHelp.getPredicate(
                root,
                dict,
                cb
            )
        }
        return dictMapper.toDto(list) as List<DictDTO>
    }

    @Cacheable(key = "'findbyid'+#p0")
    override fun findById(id: Long): DictDTO? {
        val dict = dictRepository.findById(id).orElseGet { Dict() }
        ValidationUtil.isNull(dict!!.id, "Dict", "id", id)
        return dictMapper.toDto(dict)
    }

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = [Exception::class])
    override fun create(resources: Dict): DictDTO? {
        return dictMapper.toDto(dictRepository.save(resources))
    }

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = [Exception::class])
    override fun update(resources: Dict) {
        val dict = dictRepository.findById(resources.id!!).orElseGet { Dict() }
        ValidationUtil.isNull(dict!!.id, "Dict", "id", resources.id!!)
        resources.id = dict.id
        dictRepository.save(resources)
    }

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = [Exception::class])
    override fun delete(id: Long) {
        dictRepository.deleteById(id)
    }

    @Throws(IOException::class)
    override fun download(dictDTOS: List<DictDTO>, response: HttpServletResponse?) {
        val list: MutableList<Map<String?, Any?>?> = ArrayList()
        for (dictDTO in dictDTOS) {
            if (CollectionUtil.isNotEmpty(dictDTO.dictDetails)) {
                for (dictDetail in dictDTO.dictDetails!!) {
                    val map: MutableMap<String?, Any?> = LinkedHashMap()
                    map["字典名称"] = dictDTO.name
                    map["字典描述"] = dictDTO.description
                    map["字典标签"] = dictDetail.label!!
                    map["字典值"] = dictDetail.value
                    map["创建日期"] = dictDetail.createTime
                    list.add(map)
                }
            } else {
                val map: MutableMap<String?, Any?> = LinkedHashMap()
                map["字典名称"] = dictDTO.name
                map["字典描述"] = dictDTO.description
                map["字典标签"] = null
                map["字典值"] = null
                map["创建日期"] = dictDTO.createTime
                list.add(map)
            }
        }
        downloadExcel(list, response!!)
    }
}